﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing;
using Ignitron.EEngine;
using Ignitron.EEngine.Maths;
using Ignitron.EEngine.Model;
using Ignitron.EEngine.Lighting;
using XLoader;

namespace Board3D.Models
{
    /// <summary>
    /// General model class
    /// </summary>
    internal abstract class Model: IDisposable
    {
        private GLModel mModel;
        private EModel mEModel;
        protected ETexture mTexture;

        protected EMatrix4 mModelTransMatrix;
        protected bool mTextureLoaded = false;

        // blending rendering
        private bool mBlendingRendering = false;
        private float mAlpha;

        // dynamic texture
        protected bool mHasDynamicTexture;

        public EModel Mesh
        {
            get { return mEModel; }
        }       
        
        public bool ShowNormals
        { get; set; }

        public bool LightingEnabled
        { get; set; }


        public Model()
        {
            mHasDynamicTexture = false;
            ShowNormals = false;
            LightingEnabled = true;
        }

        public Background Background
        { get; set; }

        public EMatrix4 ModelMatrix
        {
            get
            {
                return mModelTransMatrix;
            }
        }

        public void EnableBlending(float alpha)
        {
            mBlendingRendering = true;
            mAlpha = alpha;
        }

        public void DisableBlending()
        {
            mBlendingRendering = false;
        }

        public virtual EMatrix4 GetPrimaryTransformMatrix()
        {
            return EMatrix4.Identity;
        }

        protected void EnableDynamicTexture(IEngine engine, int width, int height)
        {
            mHasDynamicTexture = true;
        }

        protected void DisableDynamicTexture(IEngine engine)
        {
            mHasDynamicTexture = false;
        }

        /// <summary>
        /// TO-DO: Can we convert to IEngine interface
        /// </summary>
        public void Load(Engine engine, string sFilename)
        {
            XReader reader = new XReader();
            mModel = reader.ReadXModel(sFilename);
            if(mModel == null)
                throw new ApplicationException(string.Format("File '{0}' not found.", sFilename));

            mEModel = mModel.ToEE(engine);
            mEModel.Normalize();
            mEModel.CalculateNormals();

            mModelTransMatrix = EMatrix4.Identity;
        }

        public void LoadTexture(IEngine engine, string sFilename)
        {
            mTexture = engine.CreateTexture();
            if(mTexture.Load(sFilename) == false)
                throw new ApplicationException(string.Format("File '{0}' not found.", sFilename));                  
            mTextureLoaded = true;
        }

        public void Dispose()
        {
        }

        public virtual void Render(IEngine engine, int w, int h)
        {
            // calculate matrices
            engine.PushMatrix();
            engine.MultMatrix(ref mModelTransMatrix);

            // if not showing normals
            if(ShowNormals == false)
            {
                if (mHasDynamicTexture == true)
                {
                    engine.BeginRenderToTexture();
                    DrawDynamicTexture(engine, w, h);
                    ETexture dynamicTxt = engine.EndRenderToTexture();
                    engine.SetTexture(dynamicTxt);
                }
                else
                {
                    engine.SetTexture(mTexture);
                }

                // check blending
                if (mBlendingRendering == true)
                {
                    engine.SetAlphaBlend(mAlpha);
                }
            }

            // set material
            EMaterial material = new EMaterial();
            //material.Ambient = new EVector4(1f, 1f, 1f, 1f);
            //engine.SetMaterial(material);
            

            // render the model
            engine.RenderModel(mEModel);



            // renders normal vectors if switched on for given model
            if (ShowNormals)
            {
                engine.RenderNormals(mEModel, 2, new EVector4(0, 0, 1f, 1f));
            }


            if (mBlendingRendering == true)
            {
                engine.SetAlphaBlend(1f);
            }

            engine.PopMatrix();
        }


        protected void SetTransformMatrix(EMatrix4 matrix)
        {
            mModelTransMatrix = matrix;
        }

        /// <summary>
        /// Method for overiding for preparing the dynamic texture for the model
        /// </summary>
        protected virtual void DrawDynamicTexture(IEngine engine, int w, int h)
        {
            throw new NotImplementedException();
        }
    }
}
